import os
from selenium.common.exceptions import *
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from Config.Config import browsername_cfg
from Comm.Log import LogUtil
from time import sleep
from Comm.datetime_util import DateTimeUtil

logger = LogUtil('webdriver_base').get_logger()

driver = None
class WebDriverBase(object):
# 页面操作基础类

    def __init__(self):
        global driver
        # 如果driver不为空，直接使用原来的driver
        if driver !=  None:
            self.driver = driver
            return

        # 获取驱动
        chromeDriverPath = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'Driver', 'chromedriver.exe')
        option = webdriver.ChromeOptions()  # 实例化ChromeOptions
        option.add_argument("disable-infobars")  # 关闭浏览器提示信息
        option.add_argument('start-fullscreen')  # 浏览器全屏
        # 找浏览器的名字
        if str(browsername_cfg).lower() == 'chrome':
            # 获取谷歌的驱动
            driver = webdriver.Chrome(executable_path=chromeDriverPath, chrome_options=option)
            self.driver = driver
        else:
            logger.error("暂不支持谷歌以外的驱动")
            raise Exception("暂不支持谷歌以外的驱动")

        if self.driver == None:
            logger.error("打开浏览器驱动失败")
            raise Exception("打开浏览器驱动失败")

        self.maximize_window()


    def open_url(self, url):
        # 访问浏览器地址
        self.driver.get(url)


    def get_driver(self):
        return self.driver


    def loc_method(self, eleLoc, action, method='CSS_SELECTOR', text=None):
        """
        通用元素定位方法主入口
        :param eleLoc: 定位的元素路径
        :param action: 页面动作（输入文本，点击等等）
        :param method: 定位方式（css, path）提示：id、name、class属性都可以用css定位到，默认为CSS
        :param text: 如果是需要文本信息输入校验，才需要用到
        :return:
        """
        # loc放到selenium的driver.find_element方法就会自动识别元素
        if str(method).upper() == 'CSS_SELECTOR':
            loc = (By.CSS_SELECTOR, eleLoc)
        elif str(method).upper() == 'XPATH':
            loc = (By.XPATH, eleLoc)
        elif str(method).upper() == 'ID':
            loc = (By.ID, eleLoc)
        elif str(method).upper() == 'NAME':
            loc = (By.NAME, eleLoc)
        elif str(method).upper() == 'CLASS':
            loc = (By.CLASS_NAME, eleLoc)
        else:
            loc = None
        try:
            if loc != None:
                if action == 'click':
                    self.click(loc)
                elif action == 'send_keys':
                    self.send_keys(text, loc)
                elif action == 'select_by_text':
                    self.select_by_text(text, loc)
                elif action == 'select_by_index':
                    self.select_by_index(text, loc)
                elif action == 'select_by_value':
                    self.select_by_value(text, loc)
                elif action == 'get_element_text':
                    return self.get_element_text(loc)
                elif action == 'get_element_attribute':
                    return self.get_element_attribute(text, loc)
                elif action == 'text_in_element':
                    return self.text_in_element(text, loc)
                elif action == 'value_in_element':
                    return self.value_in_element(text, loc)
                else:
                    logger.error("action错误：请确认action值：%s" % action)
            else:
                logger.error("method错误：请确认method值：%s" % method)
        except Exception as e:
            logger.error(e)

    def send_keys(self, text, loc):
        # 输入框输入文本信息，先清除文本框内容后输入
        self.clear_input_box(loc)
        try:
            self.find_element(*loc).send_keys(text)
            sleep(1)
        except Exception as e:
            logger.error(e)
            self.get_screen_img()
            raise

    def clear_input_box(self, loc):
        # 清除输入框内容
        self.find_element(*loc).clear()
        sleep(1)

    def click(self, loc):
        # 点击
        try:
            self.find_element(*loc).click()
            sleep(2)
        except Exception as e:
            logger.error(e)
            self.get_screen_img()
            raise

    def move_to_element(self, *loc):
        # 鼠标悬停
        above = self.find_element(*loc)
        ActionChains(self.driver).move_to_element(above).perform()

    def close_single_window(self):
        # 关闭当前窗口（单个的）
        self.driver.close()

    def quit_browser(self):
        # 退出浏览器，关闭所有窗口
        self.driver.quit()

    def maximize_window(self):
        # 浏览器窗口最大化
        self.driver.maximize_window()

    def browser_forward(self):
        # 浏览器前进
        self.driver.forward()

    def browser_back(self):
        # 浏览器后退
        self.driver.back()

    def browser_refresh(self):
        # 浏览器刷新
        self.driver.refresh()

    def get_element_text(self, loc):
        # 获取元素的文本
        return self.find_element(*loc).text

    def get_element_attribute(self, attributeItem, loc):
        # 获取元素的属性,可以是id,name,type或其他任意属性
        return self.find_element(*loc).get_attribute(attributeItem)

    def implicitly_wait(self, seconds):
        # 隐式等待时间,最长等待seconds秒，超过抛出超时异常，常用于页面加载等待
        self.driver.implicitly_wait(seconds)

    def select_by_index(self, index, *loc):
        # 通过index 下标取select
        ele = self.find_element(*loc)
        Select(ele).select_by_index(index)
        sleep(1)

    def text_in_element(self, text, *loc, timeout=10):
        # 判断某个元素的text是否包含了预期的值
        # 没定位到元素返回False，定位到元素返回判断结果布尔值true
        try:
            ele = WebDriverWait(self.driver, timeout, 1).until(EC.text_to_be_present_in_element(*loc, text))
        except TimeoutException:
            logger.error("查找超时，%s不在元素的文本里面" % text)
            return False
        return ele

    def value_in_element(self, value, *loc, timeout=10):
        # 判断某个元素的value是否包含了预期的值
        # 没定位到元素返回False，定位到元素返回判断结果布尔值true
        try:
            ele = WebDriverWait(self.driver, timeout, 1).until(EC.text_to_be_present_in_element_value(*loc, value))
        except TimeoutException:
            logger.info("查找超时,%s不在元素的value里面" % value)
            return False
        return ele

    def find_element(self, *loc):
        """
        定位元素
        :param loc: 元组 示例：(By.CSS,'id')
        :return:
        """
        try:
            WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(*loc).is_displayed())
            return self.driver.find_element(*loc)
        except NoSuchElementException:
            logger.error("找不到定位的元素:%s" % loc[1])
            raise
        except TimeoutException:
            logger.error("元素查找超时:%s" % loc[1])
            raise

    def get_screen_img(self):
        #截图保存ui运行结果
        imgPath = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'Screenshots')
        screenName = DateTimeUtil().get_current_time() + '.png'
        screenFile = os.path.join(imgPath, screenName)
        try:
            self.driver.get_screenshot_as_file(screenFile)
        except Exception as e:
            logger.error("没有成功截到图，原因是: %s" % e)

    def switch_to_next_window(self, currentHandle):
        # 当打开的窗口不是当前窗口，就切换
        allHandles = self.driver.window_handles
        for handle in allHandles:
            if handle != currentHandle:
                self.driver.switch_to.window(handle)
                break

    def switch_to_next_frame(self, iframe):
        # 表单切换到iframe，其中iframe是id
        self.driver.switch_to.frame(iframe)

    def execute_script(self, js):
        #执行js命令
        self.driver.execute_script(js)